"""
Case Type   : 系统内部使用工具
Case Name   : 备机1build备2级联备
Create At   : 2022/06/08
Owner       : opentestcase012
Description :
    1.备1节点初始化数据库
    2.备2节点配置guc参数
    3.级联备配置guc参数
    4.停止备1节点
    5.build级联备并查询备2级联备情况
    6.清理环境
Expect      :
    1.数据库初始化成功
    2.guc参数配置成功
    3.guc参数配置成功
    4.停止成功
    5.build成功，级联备显示正常
    6.环境清理成功
History     :
"""
import os
import time
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.Common import Common
from testcase.utils.Common import CommonSH
from testcase.utils.Logger import Logger

primary_sh = CommonSH('PrimaryDbUser')


@unittest.skipIf(3 != primary_sh.get_node_num(), '非1+2环境不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.common = Common()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.standby1_root_node = Node('Standby1Root')
        self.standby1_node = Node('Standby1DbUser')
        self.standby2_root_node = Node('Standby2Root')
        self.standby2_node = Node('Standby2DbUser')
        self.sta1_host = self.standby1_node.ssh_host
        self.sta2_host = self.standby2_node.ssh_host
        self.port = self.standby1_node.db_port
        self.sta2_comsh = CommonSH('Standby2DbUser')
        self.dn_path = os.path.join(os.path.dirname(macro.DB_INSTANCE_PATH),
                                    'dn_path')
        self.conf_path = os.path.join(macro.DB_INSTANCE_PATH,
                                      macro.DB_PG_CONFIG_NAME)

    def test_gs_ctl(self):
        text = '----step1:在备1执行init数据库 expect:成功----'
        self.log.info(text)
        mkdir_cmd = f'rm -rf {self.dn_path};' \
                    f'mkdir {self.dn_path};ls {os.path.dirname(self.dn_path)}'
        self.log.info(mkdir_cmd)
        dir_res = self.common.get_sh_result(self.standby1_node, mkdir_cmd)
        self.assertIn('dn_path', dir_res, '文件夹创建失败')

        init_cmd = f'source {macro.DB_ENV_PATH};' \
                   f'gs_initdb {self.dn_path} -w"{macro.COMMON_PASSWD}" ' \
                   f'--nodename=single'
        self.log.info(init_cmd)
        init_res = self.common.get_sh_result(self.standby1_node, init_cmd)
        self.assertIn('Success', init_res, 'init失败')

        text = '----step2:在备2节点配置guc参数 expect:成功----'
        self.log.info(text)
        text = '----查看主机名----'
        self.log.info(text)
        global sta2_nodename
        sta1_nodename = self.common.get_sh_result(self.standby1_root_node,
                                                  "uname -n")
        sta2_nodename = self.common.get_sh_result(self.standby2_root_node,
                                                  "uname -n")
        self.assertIsNotNone(sta1_nodename, '执行失败:' + text)
        self.assertIsNotNone(sta2_nodename, '执行失败:' + text)

        local_port = int(self.port) + 1
        localheartbeatport = int(self.port) + 5
        localservice = int(self.port) + 4
        for num in range(10):
            flag = 0
            new_port = self.common.get_not_used_port(self.standby1_node)
            self.log.info(new_port)
            self.assertNotEqual(0, new_port, '端口为0')
            remote_port = int(new_port) + 1
            remoteheartbeatport = int(new_port) + 5
            remoteservice = int(new_port) + 4
            port_lis = [remote_port, remoteheartbeatport, remoteservice]
            self.log.info(port_lis)
            for port in port_lis:
                check_res = self.standby2_root_node.sh(
                    f'netstat -tlnp | grep {port}').result()
                self.log.info(check_res)
                if check_res:
                    flag = 1
                    break
            if flag == 1:
                continue
            else:
                break
        global slot_name
        slot_name = f'single_{self.sta1_host}_{remote_port}'
        self.log.info(slot_name)
        guc_cmd = f'source {macro.DB_ENV_PATH};' \
                  f'gs_guc reload -D {macro.DB_INSTANCE_PATH} ' \
                  f'-N {sta2_nodename} -c ' \
                  f'"replconninfo3 = \'localhost={self.sta2_host} ' \
                  f'localport={local_port} ' \
                  f'localheartbeatport={localheartbeatport} ' \
                  f'localservice={localservice} ' \
                  f'remotehost={self.sta1_host} ' \
                  f'remoteport={remote_port} ' \
                  f'remoteheartbeatport={remoteheartbeatport} ' \
                  f'remoteservice={remoteservice}\'"'
        self.log.info(guc_cmd)
        guc_res = self.common.get_sh_result(self.standby2_node, guc_cmd)
        self.assertIn('Success to perform gs_guc', guc_res, 'guc设置失败')

        text = '----step3:在级联备机配置guc参数 expect:成功----'
        self.log.info(text)
        az_cmd = f'cat {self.conf_path} | grep AZ'
        self.log.info(az_cmd)
        available_zone = self.common.get_sh_result(self.standby2_node,
                                                   az_cmd).split('\'')[-2]
        guc_cmd1 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} ' \
                   f'-N {sta1_nodename} -c ' \
                   f'"replconninfo1 = \'localhost={self.sta1_host} ' \
                   f'localport={remote_port} ' \
                   f'localheartbeatport={remoteheartbeatport} ' \
                   f'localservice={remoteservice} ' \
                   f'remotehost={self.sta2_host} ' \
                   f'remoteport={local_port} ' \
                   f'remoteheartbeatport={localheartbeatport} ' \
                   f'remoteservice={localservice}\'"'
        self.log.info(guc_cmd1)
        guc_res1 = self.common.get_sh_result(self.standby1_node, guc_cmd1)
        self.assertIn('Success to perform gs_guc', guc_res1, 'guc设置失败')

        guc_cmd2 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} -c ' \
                   f'"listen_addresses=\'localhost,{self.sta1_host}\'"'
        self.log.info(guc_cmd2)
        guc_res2 = self.common.get_sh_result(self.standby1_node, guc_cmd2)
        self.assertIn('Success to perform gs_guc', guc_res2, 'guc设置失败')

        guc_cmd3 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} -c ' \
                   f'"port=\'{new_port}\'"'
        self.log.info(guc_cmd3)
        guc_res3 = self.common.get_sh_result(self.standby1_node, guc_cmd3)
        self.assertIn('Success to perform gs_guc', guc_res3, 'guc设置失败')

        guc_cmd4 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} -c ' \
                   f'"local_bind_address=\'{self.sta1_host}\'"'
        self.log.info(guc_cmd4)
        guc_res4 = self.common.get_sh_result(self.standby1_node, guc_cmd4)
        self.assertIn('Success to perform gs_guc', guc_res4, 'guc设置失败')

        guc_cmd5 = f'source {macro.DB_ENV_PATH};' \
                   f'gs_guc set -D {self.dn_path} -c ' \
                   f'"available_zone=\'{available_zone}\'"'
        self.log.info(guc_cmd5)
        guc_res5 = self.common.get_sh_result(self.standby1_node, guc_cmd5)
        self.assertIn('Success to perform gs_guc', guc_res5, 'guc设置失败')

        text = '----step4:重启备1数据库 expect:成功----'
        self.log.info(text)
        rest_cmd = f'source {macro.DB_ENV_PATH};' \
                   f'gs_ctl restart -D {macro.DB_INSTANCE_PATH};'
        self.log.info(rest_cmd)
        time.sleep(10)
        rest_res = self.common.get_sh_result(self.standby1_node, rest_cmd)
        self.assertIn('server started', rest_res, '备1重启失败')

        text = '----step5:build级联备并查询数据库状态 expect:成功----'
        self.log.info(text)
        build_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_ctl build -b standby_full -D {self.dn_path} ' \
                    f'-C "localhost={self.sta1_host} localport={new_port} ' \
                    f'remotehost={self.sta1_host}  remoteport={self.port}" ' \
                    f'-M cascade_standby'
        build_res = self.common.get_sh_result(self.standby1_node, build_cmd)
        self.assertIn('server started', build_res, '备机build失败')
        time.sleep(10)

        query_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_ctl query -D {macro.DB_INSTANCE_PATH};'
        self.log.info(query_cmd)
        query_res = self.common.get_sh_result(self.standby2_node, query_cmd)
        self.assertIn('Cascade Standby', query_res, '备2级联备build失败')

    def tearDown(self):
        text = "----step6:恢复环境 expect:成功----"
        self.log.info(text)
        stop_cmd = f'source {macro.DB_ENV_PATH};' \
                   f'gs_ctl stop -D {self.dn_path}'
        self.log.info(stop_cmd)
        stop_res = self.common.get_sh_result(self.standby1_node, stop_cmd)
        del_cmd = f'rm -rf {self.dn_path};ls {os.path.dirname(self.dn_path)}'
        self.log.info(del_cmd)
        del_res = self.common.get_sh_result(self.standby1_root_node, del_cmd)
        guc_cmd = f'source {macro.DB_ENV_PATH};' \
                  f'gs_guc set -D {macro.DB_INSTANCE_PATH} ' \
                  f'-N {sta2_nodename} -c ' \
                  f'"replconninfo3 = \'\'"'
        self.log.info(guc_cmd)
        guc_res = self.common.get_sh_result(self.standby2_node, guc_cmd)
        drop_cmd = f"SELECT * FROM pg_drop_replication_slot('{slot_name}');"
        self.log.info(drop_cmd)
        res = self.sta2_comsh.execut_db_sql(drop_cmd, dbname='postgres')
        restart_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'gs_om -t restart'
        self.log.info(restart_cmd)
        restart_res = self.common.get_sh_result(self.standby2_node, restart_cmd)
        self.log.info(restart_res)
        self.assertIn('server stopped', stop_res, '新build备机数据库停止失败')
        self.assertIn('pg_drop_replication_slot', res, '逻辑复制槽删除失败')
        self.assertNotIn('dn_path', del_res, '文件删除失败')
        self.assertIn('Success to perform gs_guc', guc_res, 'guc设置失败')
        self.assertIn('Successfully started.', restart_res, '数据库重启失败')
        self.log.info(f'----{os.path.basename(__file__)} finish----')
